package com.begamer.card.common.util.binRead;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;

import org.apache.log4j.Logger;

import com.begamer.card.common.util.ByteArray;

public class BinReader {
	private static final Logger logger = Logger.getLogger(BinReader.class);
	public static String RES_DIR = "WebRoot/res";//默认资源所在目录
	public static final byte CHAR_VARS_START = ';';
	public static final byte CHAR_COMMENT_START = '/';
	
	/**
	 * 解析数据
	 * @param fileName
	 * @param clazz
	 */
	public void parseFile(String fileName,Class<? extends PropertyReader> clazz) {
		try{
			Object o = clazz.newInstance();
			((PropertyReader)o).resetData();//重置数据
			
			FileInputStream fis = new FileInputStream(new File(fileName));
			DataInputStream dis = new DataInputStream(fis);
			byte[] b = new byte[fis.available()];
			dis.readFully(b);
			//解密
			byte[] b2 = new byte[b.length];
			for(int k=0;k<b2.length;k++)
			{
				b2[k] = (byte)(~(b[k]-8) & 0xFF);
			}
			ByteArray ba =null;
//			if(clazz.equals(ResManagerData.class))
//			{
//				ba = new ByteArray(b);
//			}
//			else
//			{
				ba = new ByteArray(b2);
//			}
			int rows = ba.readInt();
			int cols = ba.readInt();
			Field[] fields = null;
			for(int i=0;i<rows;i++){
				String[] strs = new String[cols];
				for(int j=0;j<cols;j++){
					strs[j] = ba.readUTF().trim();
				}
				if(strs[0].length() == 0){
					continue;
				}
				if(strs[0].charAt(0) == CHAR_COMMENT_START){
					continue;
				} else if(strs[0].charAt(0) == CHAR_VARS_START){
					fields = getFields(clazz,strs);
				} else {
					parseLine(strs,fields,clazz);
				}
			}
			fis.close();
			dis.close();
		} catch(Exception e){
			logger.debug("读取文件：" + fileName + "出错",e);
			e.printStackTrace();
		}
	}
	
	
	/**
	 * lt@2012.2.17
	 * @param filename
	 * @param clazz
	 */
	public void parseFile2(String filename,Class<? extends PropertyReader> clazz)
	{
		int i=0;
		try{
			Object o = clazz.newInstance();
			((PropertyReader)o).resetData();//重置数据
			
			FileInputStream fis = new FileInputStream(new File(filename));
			byte[] b = new byte[fis.available()];
			fis.read(b);
			fis.close();
			//解密
			byte[] b2 = new byte[b.length];
			for(int k=0;k<b2.length;k++)
			{
				b2[k] = (byte)(~(b[k]-8) & 0xFF);
			}
			
			//ByteArray ba = new ByteArray(b);
			ByteArray ba = new ByteArray(b2);
			int rows = ba.readInt();
			int cols = ba.readInt();
			for(;i<rows;i++){
				String[] strs = new String[cols];
				for(int j=0;j<cols;j++){
					strs[j] = ba.readUTF();
				}
				if(strs[0].trim().length()==0){
					break;
				}else if(strs[0].charAt(0) == CHAR_COMMENT_START){
					continue;
				} else if(strs[0].charAt(0) == CHAR_VARS_START){
					continue;
				} else {
					((PropertyReader)clazz.newInstance()).parse(strs);
				}
			}
		} catch(Exception e){
			logger.error("i="+i);
			logger.error("读取数据文件" + filename + "出错：", e);
		}
	}
	
	/**
	 * 解析一行
	 * @param value
	 * @param fields
	 * @param clazz
	 * @throws Exception
	 */
	protected void parseLine(String[] value,Field[] fields,Class<? extends PropertyReader> clazz) throws Exception{
		Object o = clazz.newInstance();
		for(int i=0;i<fields.length;i++){
			Field f = fields[i];
			if(f == null){
				continue;
			} 
			if(f.getType().equals(int.class)){
				f.setInt(o,decodeInt(value[i]));
			} else if(f.getType().equals(double.class)) {
				f.setDouble(o,decodeDouble(value[i]));
			} else if(f.getType().equals(int[].class)){
				f.set(o,parseIntArray(value,i));
			} else if(f.getType().equals(double[].class)){
				double[] r = new double[value.length-i];
				for(int j=0;j<r.length;j++){
					r[j] = decodeDouble(value[i+j]);
				}
				f.set(o,r);
			} else if(f.getType().equals(String[].class)){
				f.set(o,parseStringArray(value,i));
			} else if(f.getType().equals(long.class)){
				f.setLong(o, decodeLong(value[i]));
			}else if(f.getType().equals(float.class))
			{
				f.setFloat(o, decodeFloat(value[i]));
			}
			else{
				f.set(o,value[i]);
			}
		}
		((PropertyReader)o).addData();
	}
	
	/**
	 * 将字符串数组从指定索引转化成字符串数组
	 * 字符串数组将不包含指定索引
	 * @param value
	 * @param startIndex
	 * @return
	 */
	protected String[] parseStringArray(String[] value,int startIndex){
		String[] r = new String[value.length-startIndex];
		System.arraycopy(value, startIndex, r, 0, r.length);
		
		int len = 0;
		for(int i=0;i<r.length;i++){
			if(r[i].length() > 0){
				len ++;
			}
		}
		if(len == r.length){
			return r;
		} else {
			String[] d = new String[len];
			for(int i=0,j=0;i<r.length;i++){
				if(r[i].length() > 0){
					d[j] = r[i];
					j++;
				}
			}
			return d;
		}
	}
	
	
	/**
	 * 将字符串数组从指定索引转化成int数组
	 * int数组将不包含指定索引
	 * @param value
	 * @param startIndex
	 * @return
	 */
	protected int[] parseIntArray(String[] value,int startIndex){
		int[] r = new int[value.length-startIndex];
		int length = 0;
		for(int j=0;j<r.length;j++){
			r[j] = decodeInt(value[startIndex+j]);
			if(r[j] != 0){
				length++;
			}
		}
		if(length == r.length){
			return r;
		} else {
			//去0操作
			int[] d = new int[length];
			for(int i=0,j=0;i<r.length;i++){
				if(r[i] != 0){
					d[j] = r[i];
					j++;
				}
			}
			return d;
		}
	}
	
	/**
	 * 将字符串转化成数字
	 * @param str
	 * @return
	 */
	protected double decodeDouble(String str){
		try{
			return Double.parseDouble(str);
		} catch(Exception e){
			return 0;
		}
	}
	
	/**
	 * 将字符串转化成数字
	 * @param str
	 * @return
	 */
	protected int decodeInt(String str){
		try{
			return Integer.decode(str);
		} catch(Exception e){
			return 0;
		}
	}
	
	/**
	 * 将字符串转化成数字
	 * @param str
	 * @return
	 */
	protected long decodeLong(String str){
		try{
			return Long.decode(str);
		} catch(Exception e){
			return 0;
		}
	}
	
	protected float decodeFloat(String str){
		try{
			return Float.valueOf(str);
		} catch(Exception e){
			return 0;
		}
	}
	
	/**
	 * 根据变量名的字符串取得变量对象
	 * @param clazz
	 * @param strs
	 * @return
	 * @throws Exception
	 */
	protected Field[] getFields(Class<? extends PropertyReader> clazz,String[] strs) throws Exception{
		Field[] fields = new Field[strs.length];
		for(int i=0;i<strs.length;i++){
			String s = strs[i];
			if(s.length() > 0){
				if(s.charAt(0) == CHAR_VARS_START){
					s = s.substring(1,s.length());
				}
				fields[i] = clazz.getDeclaredField(s);
				fields[i].setAccessible(true);
			}
		}
		return fields;
	}
	
	/**
	 * 读所有文件
	 */
	public void readAllData(){
		RES_DIR=System.getProperty("card_server_pay")+"res";
		//加载数据
		parseFile(RES_DIR + "/servers.bin", ServersData.class);//游戏区服列表(应该在资源服务器上)
		parseFile(RES_DIR + "/recharge.bin", RechargeData.class);//游戏区服列表(应该在资源服务器上)
	}
	
	public static void main(String[] args){
		BinReader reader = new BinReader();
		reader.readAllData();
	}
}